//@author A0101119Y
#ifndef GCAL_H
#define GCAL_H

#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/StreamCopier.h"
#include "Poco/Path.h"
#include "Poco/URI.h"
#include "Poco/Exception.h"
#include <string>
#include <vector>
#include <assert.h>
#include "CommonObjects.h"
#include "GCalAuthHandler.h"
#include "GCalParser.h"
#include "GCalRequestAgent.h"
#include "DbMgr.h"

namespace Twentyfifth {
	class GCalMgr {
	protected:
		// the time offset is relative to local time, ie. how many seconds are we ahead of Google's time?
		int timeOffsetWithGoogle;
		DbMgr* databasePointer;
		static const std::string GOOGLE_CLIENT_ID;
		static const std::string GOOGLE_CLIENT_SECRET;
		static const std::string GCALCMD_LOGIN;
		static const std::string GCALCMD_INFO;
		static const std::string GCALCMD_QUICKADD;
		static const std::string GCALCMD_SYNC;
		static const std::string GCALCMD_LOGOUT;
		static const std::string LABEL_ID;
		static const std::string LABEL_PRIMARY;
		static const std::string LABEL_EMAIL_ADDRESS;
		static const std::string LABEL_TIME_ZONE;
		static const std::string LABEL_TOKEN_EXPIRY;
		static const std::string LABEL_LAST_UPDATED;
		static const std::string LABEL_CALENDAR_NAME_REMOTE;
		static const std::string LABEL_CALENDAR_ID_REMOTE;
		static const std::string LABEL_CALENDAR_ID_LOCAL;
		static const std::string VALUE_CALENDAR_NAME;
		static const std::string MSG_SUCCESS_SYNC;
		static const std::string MSG_ERR_CLEARED_ALL;
		static const std::string MSG_ERR_NO_STRING_FOR_ADD;
		static const std::string MSG_ERR_GENERAL;
		static const std::string MSG_ERR_INVALID_COMMAND;
		static const std::string MSG_ERR_NOT_LOGGED_IN;
		static const std::string MSG_ERR_FULL_DAY_TASK;
		enum GCalCmdType { INVALID, LOGIN, INFO, QUICKADD, SYNC, LOGOUT };
		struct GCalCmd {
			GCalCmd() : cmdtype(INVALID) {}
			GCalCmdType cmdtype;
			std::string value;
		};
		GCalCmd parse(std::string userInput);
		Status login();
		Status info();
		Status quickAdd(std::string quickAddString);
		Status logout();

		void executeOnLogin();
		void getCredentials();
		void linkToCalendar();
		void checkAndRenewAccessToken();

		std::string getCalendarId(std::vector<std::map<std::string, std::string>> JSONResponseFromGetCalendars);
		void syncTask(Task& local, Task remote);
		Status syncTimedTasks(DbMgr&);
		void updateLocalTask(Task& local, Task remote);
		void updateRemoteTask(Task& local, Task remote);
		int getSpaceAfterFirstWord(std::string);
		std::string removeFirstWord(std::string);
		std::string getFirstWord(std::string);
		std::string getEventsFromRemote();
		void addTaskToRemote(Task&);
		void deleteTaskFromRemote(Task&);
		int getServerTimeOffset();
	public:
		void setDbMgr(DbMgr&);
		Status executeCommand(std::string);
		bool isLoggedIn();
		Status syncDatabase(DbMgr&);
	};
}

#endif